package cn.uai.activiti8.service.impl;

import cn.uai.activiti8.approval.bus.BusinessBus;
import cn.uai.activiti8.approval.service.DeployService;
import cn.uai.activiti8.approval.service.InfrastructureService;
import cn.uai.activiti8.cache.GlobalCache;
import cn.uai.activiti8.dto.Result;
import cn.uai.activiti8.entity.ActionHistory;
import cn.uai.activiti8.entity.ApplyProcessInstance;
import cn.uai.activiti8.entity.User;
import cn.uai.activiti8.enums.RespCodeEnum;
import cn.uai.activiti8.enums.RunningStatusEnum;
import cn.uai.activiti8.mapper.ActionHistoryMapper;
import cn.uai.activiti8.mapper.ApplyProcessInstanceMapper;
import cn.uai.activiti8.service.PortalService;
import cn.uai.activiti8.service.UserService;
import cn.uai.activiti8.util.TimeFormatter;
import com.alibaba.fastjson2.JSONObject;
import jakarta.annotation.Resource;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Map;

/**
 * @desc 门户服务类
 * @author uai
 * @since 2025/8/7 10:28
 * @version 1.0
 */
@Service
public class PortalServiceImpl implements PortalService, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Resource
    private UserService userService;

    @Resource
    private ActionHistoryMapper actionHistoryMapper;

    @Resource
    private ApplyProcessInstanceMapper applyProcessInstanceMapper;
    
    @Resource
    private DeployService deployService;

    @Resource
    private InfrastructureService infrastructureService;

    @Override
    public String start(String body) {
        JSONObject bodyJson = JSONObject.parseObject(body);
        Long uid = bodyJson.getLong("uid");
        User user = userService.find(uid);
        if (null == user) {
            return Result.exception(RespCodeEnum.USER_NOT_EXIST);
        }
        String processModel = bodyJson.getString("processModel");
        BusinessBus bus = (BusinessBus) getApplicationContext().getBean(GlobalCache.PLUGINS.get(processModel));
        ProcessInstance processInstance = bus.start(body);
        // 将流程实例ID和申请信息保存到数据库中
        ApplyProcessInstance applyProcessInstance = new ApplyProcessInstance();
        applyProcessInstance.setApplicant(bodyJson.getString("applicant"));
        applyProcessInstance.setType(bodyJson.getInteger("type"));
        applyProcessInstance.setReason(bodyJson.getString("reason"));
        if (null != bodyJson.getString("startDate")) {
            applyProcessInstance.setStartDate(TimeFormatter.formatWithParse(bodyJson.getString("startDate")));
        }
        if (null != bodyJson.getString("endDate")) {
            applyProcessInstance.setEndDate(TimeFormatter.formatWithParse(bodyJson.getString("endDate")));
        }
        applyProcessInstance.setProcessInstanceId(processInstance.getId());
        applyProcessInstance.setStatus(RunningStatusEnum.RUNNING.ordinal());
        applyProcessInstance.setCreateTime(LocalDateTime.now());
        applyProcessInstance.setUpdateTime(LocalDateTime.now());
        applyProcessInstanceMapper.insert(applyProcessInstance);
        String format = TimeFormatter.format(applyProcessInstance.getCreateTime());
        return Result.success(Map.of("processInstanceId", processInstance.getId(), "time", format));
    }

    @Override
    public String complete(String body) {
        JSONObject bodyObj = JSONObject.parseObject(body);
        Long uid = bodyObj.getLong("uid");
        String note = bodyObj.getString("note");
        Integer actionType = bodyObj.getInteger("actionType");
        String processInstanceId = bodyObj.getString("processInstanceId");
        String processModel = bodyObj.getString("processModel");
        BusinessBus bus = (BusinessBus) getApplicationContext().getBean(GlobalCache.PLUGINS.get(processModel));
        ActionHistory actionHistory = new ActionHistory();
        actionHistory.setUid(uid);
        actionHistory.setNote(note);
        actionHistory.setActionType(actionType);
        actionHistory.setCreateTime(LocalDateTime.now());
        actionHistory.setProcessInstanceId(processInstanceId);
        actionHistoryMapper.insert(actionHistory);
        return bus.complete(body);
    }

    @Override
    public String completeDelegation(String body) {
        JSONObject bodyJson = JSONObject.parseObject(body);
        BusinessBus bus = (BusinessBus) getApplicationContext().getBean(GlobalCache.PLUGINS.get(bodyJson.getString("processModel")));
        return bus.completeDelegation(body);
    }

    @Override
    public String claim(String body) {
        return infrastructureService.claim(body);
    }

    @Override
    public String assign(String body) {
        return infrastructureService.assign(body);
    }

    @Override
    public String delegate(String body) {
        JSONObject bodyJson = JSONObject.parseObject(body);
        BusinessBus bus = (BusinessBus) getApplicationContext().getBean(GlobalCache.PLUGINS.get(bodyJson.getString("processModel")));
        return bus.delegate(body);
    }

    @Override
    public String reject(String body) {
        return infrastructureService.reject(body);
    }

    @Override
    public String reject2Apply(String body) {
        return infrastructureService.reject2Apply(body);
    }

    @Override
    public String reject2Any(String body) {
        return infrastructureService.reject2Any(body);
    }

    @Override
    public String taskQuery(Long uid) {
        return infrastructureService.taskQuery(uid);
    }

    @Override
    public String taskQuery(String userName) {
        return infrastructureService.taskQuery(userName);
    }

    @Override
    public String candidateUserTaskQuery(String userName) {
        return infrastructureService.candidateUserTaskQuery(userName);
    }

    @Override
    public String candidateGroupTaskQuery(String groupName) {
        return infrastructureService.candidateGroupTaskQuery(groupName);
    }

    @Override
    public String deploy(String body) {
        return deployService.deploy(body);
    }

    @Override
    public String processDefinitionQuery(String deployId) {
        return deployService.processDefinitionQuery(deployId);
    }

    @Override
    public String processDefinitionDeployQuery(String processDefinitionName) {
        return deployService.processDefinitionDeployQuery(processDefinitionName);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public ApplicationContext getApplicationContext() {
        return this.applicationContext;
    }
}
